package com.jshoperxms.shiro;

import com.jshoperxms.controller.utils.SHA1;
import com.jshoperxms.controller.utils.enums.BaseEnums;
import com.jshoperxms.controller.utils.enums.BasicUserEnums;
import com.jshoperxms.controller.utils.statickey.TagWords;
import com.jshoperxms.entity.*;
import com.jshoperxms.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by sdywcd on 16/11/3.
 * Des:
 */
public class MyShiroRealm extends AuthorizingRealm{

    private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);

    @Resource
    private BasicUserTService basicUserTService;

    @Resource
    private SysUserRoleRpTService sysUserRoleRpTService;

    @Resource
    private SysRoleTService sysRoleTService;

    @Resource
    private SysRoleModuleActionRpTService sysRoleModuleActionRpTService;

    @Resource
    private SysModuleActionTService sysModuleActionTService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        logger.info("#######执行Shiro权限认证########");
        String loginName = (String)super.getAvailablePrincipal(principalCollection);
        //查询用户
        Criterion criterion= Restrictions.eq("username",loginName);
        BasicUserT basicUserT=this.basicUserTService.findOneByCriteria(BasicUserT.class,criterion);
        if(basicUserT!=null){

            //获取用户的所有角色,和权限
            Set<String> userRoles=new HashSet<>();
            List<String> userPermissions=new ArrayList<>();
            Criterion criterion2= Restrictions.eq(TagWords.STATUS, BaseEnums.DataUsingState.USING.getState());
            criterion2=Restrictions.and(criterion2).add(Restrictions.eq("basicuserid",basicUserT.getId()));
            List<SysUserRoleRpT>list=this.sysUserRoleRpTService.findByCriteria(SysUserRoleRpT.class, criterion2);
            if(!list.isEmpty()){
                for(SysUserRoleRpT s:list){
                    SysRoleT bean=this.sysRoleTService.findByPK(SysRoleT.class,s.getSysroleid());
                    if(bean!=null){
                        userRoles.add(bean.getSysrolename());
                        //获取角色权限信息
                        Criterion criterion1=Restrictions.eq("sysroleid",bean.getId());
                        List<SysRoleModuleActionRpT>sysRoleModuleActionRpTs=this.sysRoleModuleActionRpTService.findByCriteria(SysRoleModuleActionRpT.class,criterion1);
                        if(!sysRoleModuleActionRpTs.isEmpty()){
                            for(SysRoleModuleActionRpT s1:sysRoleModuleActionRpTs){
                                SysModuleActionT sysm=this.sysModuleActionTService.findByPK(SysModuleActionT.class,s1.getSysmoduleactionid());
                                if(sysm!=null){
                                    userPermissions.add(sysm.getPermission());
                                }
                            }

                        }
                    }
                }
            }
            // 或者按下面这样添加
            //添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色
//            simpleAuthorInfo.addRole("admin");
            //添加权限
//            simpleAuthorInfo.addStringPermission("admin:manage");
//            logger.info("已为用户[mike]赋予了[admin]角色和[admin:manage]权限");
            //权限信息对象info,用来存放用户的所有角色和权限
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
            info.setRoles(userRoles);
            for(String s:userPermissions){
                info.addStringPermission(s);
            }
            return info;
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        LoginUsernamePasswordToken token= (LoginUsernamePasswordToken) authenticationToken;
        logger.info("验证当前Subject时获取到token为：" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
        Map<String,String> params=new HashMap<String,String>();
        params.put("username", StringUtils.trim(token.getUsername()));
        params.put("userstatus", BasicUserEnums.UserStatus.ACTIVE.getState());
        params.put("status", BaseEnums.DataUsingState.USING.getState());
        Criterion criterion=Restrictions.allEq(params);
        BasicUserT basicUserT=this.basicUserTService.findOneByCriteria(BasicUserT.class, criterion);
        if(basicUserT!=null){
            // 若存在，将此用户存放到登录认证info中，无需自己做密码对比，Shiro会为我们进行密码对比校验
            return new SimpleAuthenticationInfo(basicUserT, basicUserT.getPassword(), ByteSource.Util.bytes(basicUserT.getSalt()), getName());
        }
        return null;
    }
}
